[[ 文字列 ~= 正規表現 ]] パターンマッチ
複合コマンド [[ では =~ 演算子で拡張正規表現でのパターンマッチを行うことができます。
if [[ 2023-01-02 =~ ^([0-9]{4})-([0-9]{2})-([0-9]{2})$ ]]; then
echo "マッチしました"
fi
左辺の文字列が右辺の正規表現にマッチした場合の結果は 0 で、マッチしなかった場合の結果は 1 になります。また右辺の正規表現が文法的に間違っている場合の結果は 2 になります。
[[ apple =~ ^apple$ ]]
echo "結果=$? : マッチした場合"
[[ apple =~ ^app$ ]]
echo "結果=$? : マッチしなかった場合"
[[ apple =~ []{} ]]
echo "結果=$? : 文法的に間違っている場合"
マッチしたパターンは BASH_REMATCH に格納されます。BASH_REMATCH は配列で 0 番目にはマッチした文字列がすべて格納されます。1 ~ は キャプチャされたパターンが設定されます。
[[ 2023-01-02 =~ ^([0-9]{4})-([0-9]{2})-([0-9]{2})$ ]]
echo "BASH_REMATCH[0] = ${BASH_REMATCH[0]}"
echo "BASH_REMATCH[1] = ${BASH_REMATCH[1]}"
echo "BASH_REMATCH[2] = ${BASH_REMATCH[2]}"
echo "BASH_REMATCH[3] = ${BASH_REMATCH[3]}"
以下は BASH_REMATCH を使用して文字列を置換するサンプルです。
# BASH_REMATCHを使って文字列置換
str=東京都
[[ ${str} =~ ^(.+?)(都|道|府|県)$ ]]
echo "${BASH_REMATCH[@]}"
str="${BASH_REMATCH[1]}駅"
echo "${str}"
パターンをクォートで囲んだ場合、正規表現としてではなく文字列としてマッチングが行われます。
[[ 2023-01-02 =~ "^([0-9]{4})-([0-9]{2})-([0-9]{2})$" ]]
echo "結果=$? BASH_REMATCH=${BASH_REMATCH[@]}"
[[ 2023-01-02 =~ "2023-01-02" ]]
echo "結果=$? BASH_REMATCH=${BASH_REMATCH[@]}"
変数に設定されているパターンでマッチングを行うこともできます。この場合もクォートで囲んだ場合、正規表現としてではなく文字列としてマッチングが行われます。
pattern='^([0-9]{4})-([0-9]{2})-([0-9]{2})$'
[[ 2023-01-02 =~ "${pattern}" ]]
echo "結果=$? BASH_REMATCH=${BASH_REMATCH[@]}"
[[ 2023-01-02 =~ ${pattern} ]]
echo "結果=$? BASH_REMATCH=${BASH_REMATCH[@]}"
パターンの正規表現は拡張正規表現のため \s や \w、\d のような Perlの正規表現は使用できません。
str='123 '
# \d, \s などは使用できないのでマッチしない
[[ ${str} =~ ^\d+\s*$ ]]
echo "結果=$?"
# これらはマッチする
# 正規表現でスペースを使う場合はエスケープかクォートが必要
[[ ${str} =~ ^[[:digit:]]+[[:space:]]*$ ]]
echo "結果=$?"
[[ ${str} =~ ^[0-9]+\ *$ ]]
echo "結果=$?"
[[ ${str} =~ ^[0-9]+' '*$ ]]
echo "結果=$?"
str=$'1\n2\n3'
# このような指定方法で改行にマッチさせることができる
[[ ${str} =~ ^1$'\n'2$'\n'3$ ]]
echo "結果=$?"
# [[:space:]]は[ \t\n\r\f\v]にマッチ
[[ ${str} =~ ^1[[:space:]]2[[:space:]]3$ ]]
echo "結果=$?"